import {
	ListActionType,
	IListStore,
	IListAbility,
	IListController,
	IListControllerParams,
	IParam,
	ICodeListItem,
	IListModel,
	IViewLogicInput,
	ICtrlActionResult,
	IUIService,
	IEntityDetail,
} from '@/core/interface';
import { AuthUtil, deepCopy } from '@/core/utils';
import { MDCtrlController } from './md-ctrl-controller';

/**
 * 列表部件控制器
 *
 * @export
 * @class ListController
 * @extends {(MDCtrlController<T | ListActionType, IListStore, IListAbility>)}
 * @implements {IListController}
 * @template T
 */
export class ListController
	extends MDCtrlController<ListActionType, IListStore, IListAbility>
	implements IListController<IListStore, IListAbility>
{
	/**
	 * 数据备份
	 *
	 * @protected
	 * @type {IParam}
	 * @memberof ListController
	 */
	protected backData: IParam = [];

	/**
	 * 行激活模式 (0: 无激活、1: 单击激活、2: 双击激活)
	 *
	 * @protected
	 * @type {(0 | 1 | 2)}
	 * @memberof ListController
	 */
	protected rowActiveMode!: 0 | 1 | 2;

	/**
	 * 列表部件模型
	 *
	 * @protected
	 * @type {IListModel}
	 * @memberof ListController
	 */
	protected declare readonly model: IListModel;

	/**
	 * Creates an instance of ListController.
	 * @param {IListControllerParams<ListActionType, IListAbility>} params
	 * @memberof ListController
	 */
	public constructor(
		params: IListControllerParams<ListActionType, IListAbility>
	) {
		super(params);
		this.rowActiveMode = params.rowActiveMode;
		this.ctrlInit(params);
	}

	/**
	 * 加载的数据是否附加在已有数据之后
	 *
	 * @type {boolean}
	 * @memberof ListController
	 */
	public isAddBehind = false;

	/**
	 * 处理加载数据变化
	 *
	 * @protected
	 * @param {IParam[]} data
	 * @memberof ListController
	 */
	protected handleLoadDataChange(data: IParam[]): void {
		if (!this.isAddBehind) {
			this.store.data = [];
		}
		if (this.model.enableGroup) {
			this.backData.push(...data);
		} else {
			this.store.data.push(...data);
		}
		// loadMore加载更多时才需要isAddBehind===true
		this.isAddBehind = false;
		this.handleGroup();
		this.handleDefaultSelect();
		this.handleItemUIActionGroup();
	}

	/**
	 * 处理项界面行为组
	 *
	 * @protected
	 * @memberof ListController
	 */
	protected handleItemUIActionGroup() {
		const { uIActionGroup } = this.model;
		if (uIActionGroup) {
			const uIActionGroupModel = deepCopy(uIActionGroup);
			this.store.data?.forEach((item: IParam) => {
				if (item && !item.isGroupItem) {
					AuthUtil.calcActionItemAuthState(
						item.getDo(),
						uIActionGroupModel,
						this.uiService as IUIService,
						this.store.viewCtx.view?.getModel()
					);
					item.uIActionGroup = uIActionGroupModel;
				}
			});
		}
	}

	/**
	 * 自动分组
	 *
	 * @protected
	 * @memberof ListController
	 */
	protected async handleAutoGroup() {
		if (this.backData.length === 0) {
			return;
		}
		//  分组属性标识
		const field = this.model.groupField as string;
		//  分组属性代码表
		const fieldCodeList = this.model.groupFieldCodeListTag;
		//  分组列标识
		const dataIndex = this.model.groupDataIndex as string;
		const resultMap: Map<string, IParam[]> = new Map();
		const codeItems: IParam[] = [];
		if (fieldCodeList) {
			const result = await App.getAppCodeListHelper().getCodeListItems(
				fieldCodeList
			);
			if (result.ok) {
				codeItems.push(...result.data);
			}
		}
		this.backData.forEach((item: IParam) => {
			const items = resultMap.get(item[field]) || [];
			items.push(item);
			resultMap.set(item[field], items);
		});
		const resultItems: IParam[] = [];
		resultMap.forEach((value: IParam[], key: string) => {
			const item =
				codeItems.length > 0
					? codeItems.find((item: IParam) => item.value === key)
					: { text: key };
			resultItems.push({
				key: `group-item__${key}`,
				srfkey: `group-item__${key}`,
				srfmajortext: item ? item.text : App.ts('widget.list.other', '其他'),
				[dataIndex]: item ? item.text : App.ts('widget.list.other', '其他'),
				isGroupItem: true,
				children: value,
			});
		});
		this.store.data = resultItems;
	}

	/**
	 * 代码表分组
	 *
	 * @protected
	 * @return {*}
	 * @memberof ListController
	 */
	protected async handleCodeListGroup() {
		//  分组代码表标识
		const codeListTag = this.model.groupCodeListTag as string;
		//  分组属性标识
		const field = this.model.groupField as string;
		//  分组列标识
		const dataIndex = this.model.groupDataIndex as string;
		if (!codeListTag) {
			return;
		}
		const { context, viewParams } = this.store;
		const result = await App.getAppCodeListHelper().getCodeListItems(
			codeListTag,
			context,
			viewParams
		);
		if (!result.ok || result.data.length === 0) {
			return;
		}
		const keys: (string | number)[] = result.data.map(
			(d: ICodeListItem) => d.value
		);
		const resultItems: IParam[] = [];
		result.data.forEach((item: ICodeListItem) => {
			const items: IParam[] = this.backData.filter(
				(d: IParam) => d[field] === item.value
			);
			resultItems.push({
				key: `group-item__${item.value}`,
				srfkey: `group-item__${item.value}`,
				srfmajortext: item.text,
				[dataIndex]: item.text,
				isGroupItem: true,
				children: items,
			});
		});
		const otherItems = this.backData.filter(
			(d: IParam) => keys.indexOf(d[field]) === -1
		);
		if (otherItems.length > 0) {
			resultItems.push({
				key: `group-other-item`,
				srfkey: `group-other-item`,
				srfmajortext: App.ts('widget.list.other', '其他'),
				[dataIndex]: App.ts('widget.list.other', '其他'),
				isGroupItem: true,
				children: otherItems,
			});
		}
		this.store.data = resultItems;
	}

	/**
	 * 加载更多
	 *
	 * @memberof ListController
	 */
	public loadMore() {
		this.store.curPage += 1;
		this.isAddBehind = true;
		this.load();
	}

	/**
	 * 列表项单击
	 *
	 * @param {IParam} item
	 * @param {MouseEvent} event
	 * @memberof ListController
	 */
	public handleItemClick(item: IParam, event: MouseEvent) {
		const selections = this.store.selections;
		if (this.singleSelect) {
			selections.length = 0;
			selections.push(item);
		} else {
			const index = selections.findIndex(
				(select: IParam) => select.srfkey === item.srfkey
			);
			//	未选中
			if (index === -1) {
				this.store.selections.push(item);
			} else {
				this.store.selections.splice(index, 1);
			}
		}
		this.emit('selectionChange', this.getData());
		if (this.rowActiveMode === 1) {
			this.emit('dataActive', [item]);
		}
	}

	/**
	 * 列表项双击
	 *
	 * @param {IParam} item
	 * @param {MouseEvent} event
	 * @memberof ListController
	 */
	public handleItemDbClick(item: IParam, event: MouseEvent) {
		const selections = this.store.selections;
		if (this.singleSelect) {
			selections.length = 0;
			selections.push(item);
		} else {
			const index = selections.findIndex(
				(select: IParam) => select.srfkey === item.srfkey
			);
			//	未选中
			if (index === -1) {
				this.store.selections.push(item);
			} else {
				this.store.selections.splice(index, 1);
			}
		}
		this.emit('selectionChange', this.getData());
		if (this.rowActiveMode === 2) {
			this.emit('dataActive', [item]);
		}
	}

	/**
	 * 选中数据
	 *
	 * @param {IParam[]} selections
	 * @memberof ListController
	 */
	public handleSelectionChange(selections: IParam[]) {
		this.store.selections = selections;
		this.emit('selectionChange', this.getData());
	}

	/**
	 * 删除
	 *
	 * @param {string} action
	 * @param {IHttpResponse} response
	 * @memberof ListController
	 */
	async remove(datas: IParam = {}): Promise<ICtrlActionResult> {
		const { removeAction } = this.actions;
		if (!removeAction) {
			App.getNotificationHelper().warning(
				App.ts('widget.common.warn', '警告'),
				App.ts('widget.list.notconfig.notconfigdeleteaction', '未配置删除行为')
			);
			return { ok: false, data: this.getData(), rowData: { status: 500 } };
		}
		const deleteItems: IParam[] = [];
		//	已选中数据
		datas.forEach((record: IParam) => {
			if (record.srfuf === '0') {
				const index = this.store.data.findIndex(
					(i: IParam) => i.srfkey === record.srfkey
				);
				if (index !== -1) {
					this.store.data.splice(index, 1);
				}
			} else {
				deleteItems.push(record);
			}
		});
		if (deleteItems.length === 0) {
			return { ok: true, data: this.getData(), rowData: { status: 200 } };
		}
		let dataInfo = '';
		deleteItems.forEach((item: IParam, index: number) => {
			if (index < 5) {
				if (dataInfo !== '') {
					dataInfo += '、';
				}
				dataInfo += item.srfmajortext ? item.srfmajortext : '';
			}
		});
		if (!dataInfo) {
			dataInfo = `${App.ts('widget.list.check', '选中')}${
				deleteItems.length
			}${App.ts('widget.list.piece', '条数据')}`;
		} else {
			if (deleteItems.length < 5) {
				dataInfo += ` ${App.ts('widget.list.total', '共')}${
					deleteItems.length
				}${App.ts('widget.list.piece', '条数据')}`;
			} else {
				dataInfo += `...${deleteItems.length}${App.ts(
					'widget.list.piece',
					'条数据'
				)}`;
			}
		}
		//	去除null和undefined
		dataInfo = dataInfo.replace(/[null]/g, '').replace(/[undefined]/g, '');
		const removeData = () => {
			const { entityCodeName } = this.model;
			const entityDetails = App.getAppEntityConfig();
			const entity = entityDetails.find(
				(detail: IEntityDetail) => detail.codeName == entityCodeName
			);
			if (!entity) {
				return;
			}
			const keys: string[] = [];
			deleteItems.forEach((item: IParam) => {
				keys.push(
					item.srfkey ? item.srfkey : item[entity.keyField.toLowerCase()]
				);
			});
			if (keys.length === 0) {
				return;
			}
			const { context, viewParams } = this.store;
			let _removeAction = removeAction;
			if (Object.is(removeAction, 'RemoveTemp') && keys.length > 1) {
				_removeAction = 'RemoveBatchTemp';
			}
			const tempContext: any = deepCopy(context);
			const _keys: string[] | string = keys.length > 1 ? keys : keys[0];
			const arg = { [entityCodeName.toLowerCase()]: _keys };
			let promises: Promise<any> | null = null;
			if (keys && keys.length > 1) {
				const promiseArr: any = [];
				(_keys as string[]).forEach((ele: any) => {
					Object.assign(tempContext, { [entityCodeName.toLowerCase()]: ele });
					Object.assign(arg, { viewParams: deepCopy(viewParams) });
					Object.assign(arg, { [entityCodeName.toLowerCase()]: ele });
					promiseArr.push(
						this.ctrlService.delete(_removeAction, tempContext, arg)
					);
				});
				promises = Promise.all(promiseArr);
			} else {
				Object.assign(tempContext, { [entityCodeName.toLowerCase()]: _keys });
				Object.assign(arg, { viewParams: deepCopy(viewParams) });
				promises = this.ctrlService.delete(_removeAction, tempContext, arg);
			}
			this.beforeAsyncAction('remove', tempContext, arg);
			if (promises) {
				promises
					.then(async (response: any) => {
						this.afterAsyncAction('remove', response);
						if (!response.success && !Array.isArray(response)) {
							App.getNotificationHelper().error(
								App.ts('widget.common.error', '错误'),
								`${App.ts('widget.list.deletefail', '删除数据失败')}, ${
									response.info
								}`
							);
							return;
						} else {
							App.getNotificationHelper().success(
								'',
								App.ts('widget.list.deletesuccess', '删除数据成功')
							);
						}
						//删除items中已删除的项
						this.store.totalRecord -= deleteItems.length;
						this.emit('remove', deleteItems);
						this.store.selections = [];
						this.refresh();
					})
					.catch(async (error: any) => {
						this.afterAsyncAction('remove', error);
					});
			}
		};
		App.getDialogHelper().confirm(
			App.ts('widget.common.warn', '警告'),
			`${App.ts(
				'widget.common.confirmtodelete',
				'确认要删除'
			)}${dataInfo}, ${App.ts(
				'widget.common.delnotberecoverable',
				'删除操作将不可恢复'
			)}?`,
			() => {
				removeData();
			}
		);
		return { ok: true, data: this.getData(), rowData: { status: 200 } };
	}

	/**
	 * 获取能力
	 *
	 * @template A
	 * @return {*}  {A}
	 * @memberof ListController
	 */
	public getAbility(): IListAbility {
		return {
			...super.getAbility(),
			loadMore: this.loadMore.bind(this),
			remove: this.remove.bind(this),
		};
	}
}
